﻿using Brc_PaaS.Bll.System;
using Brc_PaaS.Common.Entity;
using Brc_PaaS.Common.Helper;
using Brc_PaaS.Common.Model.Basic;
using Brc_PaaS.Core.Redis;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System;

namespace Brc_PaaS.Api.Filters
{
    /// <summary>
    /// 验证请求header是否带有正确签名
    /// </summary>
    public class GlobalFilter : Attribute, IActionFilter
    {
        private RedisServerEntity redisServerEntity;
        private ISystem _system;
        /// <summary>
        /// 构造函数
        /// </summary>
        public GlobalFilter(IConfiguration configuration, ISystem system)
        {
            _system = system;
            redisServerEntity = configuration.GetSection("RedisConfiguration").Get<RedisServerEntity>();                                                                               
        }
        /// <summary>
        /// 执行方法后
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuted(ActionExecutedContext context)
        {

        }
        /// <summary>
        /// 执行方法前
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuting(ActionExecutingContext context)
        {
            var controllerActionDesc = context.ActionDescriptor as ControllerActionDescriptor;
            //var isExemption = controllerActionDesc.MethodInfo.GetCustomAttributes(inherit: true).Any(a => a.GetType().Equals(typeof(ExemptionAuth)));
            //如果是访问后台方法则不需要进入该过滤器进行验证
            var isExemption = controllerActionDesc.ControllerName.StartsWith("PaaS");
            if (!isExemption)
            {
                BaseResponseModel model = new BaseResponseModel() { IsSuccess = false, Msg = String.Empty };
                if (!context.HttpContext.Request.Headers.ContainsKey("Brc_Auth"))
                {
                    model.Msg = "请求格式有误，请检查请求报文";
                    context.Result = new JsonResult(model);
                    return;
                }

                var signature = context.HttpContext.Request.Headers["Brc_Auth"];
                var signArray = signature.ToString().Split("&");
                var systemId = signArray[0];
                Bas_System system = null;
                //第一各元素必须是系统Id，否则请求判定失败
                using (var redisMmanager = new RedisManager(redisServerEntity))
                {
                    system = redisMmanager.GetOrFetchFromHash<Bas_System>($"System:{systemId}", id => { return _system.GetSystem(systemId).Data; });
                }
                //--------普通鉴权开始---------
                if (system == null)
                {
                    model.Msg = "未找到应用相关信息，请联系管理员";
                    context.Result = new JsonResult(model);
                    return;
                }
                if (system.Status == 0)
                {
                    model.Msg = "应用已被禁用，如有任何问题请联系管理员";
                    context.Result = new JsonResult(model);
                    return;
                }
                //--------普通鉴权结束---------

                if (system.AuthType == 1)
                {
                    //--------安全鉴权开始---------
                    if (signArray.Length < 3)
                    {
                        model.Msg = "签名信息有误，请核实后重新发起请求";
                        context.Result = new JsonResult(model);
                        return;
                    }
                    long et;
                    var result = long.TryParse(signArray[1], out et);
                    if (!result)
                    {
                        model.Msg = "无法获取请求设定的最大时间界限";
                        context.Result = new JsonResult(model);
                        return;
                    }
                    var nowLong = DateTime.UtcNow.GetCurrnetTimeMillis();
                    if (nowLong > et)
                    {
                        model.Msg = "请求超过设定最大时间，请重新发起";
                        context.Result = new JsonResult(model);
                        return;
                    }
                    var isVerifySuccess = RSAHelper.VerifyCSharp(systemId + "&" + signArray[1], system.PublicKey, signArray[2]);
                    if (!isVerifySuccess)
                    {
                        model.Msg = "签名认证失败，请联系管理员";
                        context.Result = new JsonResult(model);
                        return;
                    }
                    //--------安全鉴权结束---------
                }
                context.HttpContext.Items.Add("appKey", systemId);






            }
        }
    }

   
}
